| @@ -56,6 +56,8 @@ gem 'uglifier', '>= 1.3.0' | ||
| 56 | 56 | gem 'select2-rails', '~> 3.5.4' | 
| 57 | 57 | gem 'jquery-rails', '~> 3.1.0' | 
| 58 | 58 | gem 'ace-rails-ap', '~> 2.0.1' | 
| 59 | +gem 'spectrum-rails' | |
| 60 | + | |
| 59 | 61 |  | 
| 60 | 62 | # geokit-rails doesn't work with geokit 1.8.X but it specifies ~> 1.5 | 
| 61 | 63 | # in its own Gemfile. | 
| @@ -314,6 +314,8 @@ GEM | ||
| 314 | 314 | simplecov-html (0.8.0) | 
| 315 | 315 | slack-notifier (0.5.0) | 
| 316 | 316 | slop (3.6.0) | 
| 317 | + spectrum-rails (1.3.4) | |
| 318 | + railties (>= 3.1) | |
| 317 | 319 | sprockets (2.11.0) | 
| 318 | 320 | hike (~> 1.2) | 
| 319 | 321 | multi_json (~> 1.0) | 
| @@ -443,6 +445,7 @@ DEPENDENCIES | ||
| 443 | 445 | select2-rails (~> 3.5.4) | 
| 444 | 446 | shoulda-matchers | 
| 445 | 447 | slack-notifier (~> 0.5.0) | 
| 448 | + spectrum-rails | |
| 446 | 449 | therubyracer (~> 0.12.1) | 
| 447 | 450 | twilio-ruby (~> 3.11.5) | 
| 448 | 451 | twitter (~> 5.8.0) | 
| @@ -6,6 +6,7 @@ | ||
| 6 | 6 | #= require json2 | 
| 7 | 7 | #= require jquery.json-editor | 
| 8 | 8 | #= require latlon_and_geo | 
| 9 | +#= require spectrum | |
| 9 | 10 | #= require ./worker-checker | 
| 10 | 11 | #= require_self | 
| 11 | 12 |  | 
| @@ -12,6 +12,7 @@ | ||
| 12 | 12 | *= require select2-bootstrap | 
| 13 | 13 | *= require jquery.json-editor | 
| 14 | 14 | *= require rickshaw | 
| 15 | + *= require spectrum | |
| 15 | 16 | *= require_tree . | 
| 16 | 17 | *= require_self | 
| 17 | 18 | */ | 
| @@ -186,3 +187,17 @@ h2 .scenario, a span.label.scenario { | ||
| 186 | 187 |  .color-success { | 
| 187 | 188 | color: #5cb85c; | 
| 188 | 189 | } | 
| 190 | + | |
| 191 | +.form-group { | |
| 192 | +  .sp-replacer { | |
| 193 | + @extend .form-control; | |
| 194 | + } | |
| 195 | + | |
| 196 | +  .sp-preview { | |
| 197 | + width: 100%; | |
| 198 | + } | |
| 199 | + | |
| 200 | +  .sp-dd { | |
| 201 | + display: none; | |
| 202 | + } | |
| 203 | +} | 
| @@ -45,6 +45,8 @@ class ScenariosController < ApplicationController | ||
| 45 | 45 | @exporter = AgentsExporter.new(:name => @scenario.name, | 
| 46 | 46 | :description => @scenario.description, | 
| 47 | 47 | :guid => @scenario.guid, | 
| 48 | + :tag_fg_color => @scenario.tag_fg_color, | |
| 49 | + :tag_bg_color => @scenario.tag_bg_color, | |
| 48 | 50 | :source_url => @scenario.public? && export_scenario_url(@scenario), | 
| 49 | 51 | :agents => @scenario.agents) | 
| 50 | 52 | response.headers['Content-Disposition'] = 'attachment; filename="' + @exporter.filename + '"' | 
| @@ -8,11 +8,11 @@ module AgentHelper | ||
| 8 | 8 |  | 
| 9 | 9 | def scenario_links(agent) | 
| 10 | 10 |      agent.scenarios.map { |scenario| | 
| 11 | - link_to(scenario.name, scenario, class: "label label-info") | |
| 11 | + link_to(scenario.name, scenario, class: "label", style: style_colors(scenario)) | |
| 12 | 12 |      }.join(" ").html_safe | 
| 13 | 13 | end | 
| 14 | 14 |  | 
| 15 | 15 | def agent_show_class(agent) | 
| 16 | 16 | agent.short_type.underscore.dasherize | 
| 17 | 17 | end | 
| 18 | -end | |
| 18 | +end | 
| @@ -0,0 +1,23 @@ | ||
| 1 | +module ScenarioHelper | |
| 2 | + | |
| 3 | + def style_colors(scenario) | |
| 4 | +    colors = { | |
| 5 | + color: scenario.tag_fg_color || default_scenario_fg_color, | |
| 6 | + background_color: scenario.tag_bg_color || default_scenario_bg_color | |
| 7 | +    }.map { |key, value| "#{key.to_s.dasherize}:#{value}" }.join(';') | |
| 8 | + end | |
| 9 | + | |
| 10 | + def scenario_label(scenario, text = nil) | |
| 11 | + text ||= scenario.name | |
| 12 | + content_tag :span, text, class: 'label scenario', style: style_colors(scenario) | |
| 13 | + end | |
| 14 | + | |
| 15 | + def default_scenario_bg_color | |
| 16 | + '#5BC0DE' | |
| 17 | + end | |
| 18 | + | |
| 19 | + def default_scenario_fg_color | |
| 20 | + '#FFFFFF' | |
| 21 | + end | |
| 22 | + | |
| 23 | +end | 
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | class Scenario < ActiveRecord::Base | 
| 2 | 2 | include HasGuid | 
| 3 | 3 |  | 
| 4 | - attr_accessible :name, :agent_ids, :description, :public, :source_url | |
| 4 | + attr_accessible :name, :agent_ids, :description, :public, :source_url, :tag_fg_color, :tag_bg_color | |
| 5 | 5 |  | 
| 6 | 6 | belongs_to :user, :counter_cache => :scenario_count, :inverse_of => :scenarios | 
| 7 | 7 | has_many :scenario_memberships, :dependent => :destroy, :inverse_of => :scenario | 
| @@ -9,6 +9,11 @@ class Scenario < ActiveRecord::Base | ||
| 9 | 9 |  | 
| 10 | 10 | validates_presence_of :name, :user | 
| 11 | 11 |  | 
| 12 | + validates_format_of :tag_fg_color, :tag_bg_color, | |
| 13 | + # Regex adapted from: http://stackoverflow.com/a/1636354/3130625 | |
| 14 | +    :with => /\A#(?:[0-9a-fA-F]{3}){1,2}\z/, :allow_nil => true, | |
| 15 | + :message => "must be a valid hex color." | |
| 16 | + | |
| 12 | 17 | validate :agents_are_owned | 
| 13 | 18 |  | 
| 14 | 19 | protected | 
| @@ -60,10 +60,14 @@ class ScenarioImport | ||
| 60 | 60 | description = parsed_data['description'] | 
| 61 | 61 | name = parsed_data['name'] | 
| 62 | 62 | links = parsed_data['links'] | 
| 63 | + tag_fg_color = parsed_data['tag_fg_color'] | |
| 64 | + tag_bg_color = parsed_data['tag_bg_color'] | |
| 63 | 65 | source_url = parsed_data['source_url'].presence || nil | 
| 64 | 66 | @scenario = user.scenarios.where(:guid => guid).first_or_initialize | 
| 65 | 67 | @scenario.update_attributes!(:name => name, :description => description, | 
| 66 | - :source_url => source_url, :public => false) | |
| 68 | + :source_url => source_url, :public => false, | |
| 69 | + :tag_fg_color => tag_fg_color, | |
| 70 | + :tag_bg_color => tag_bg_color) | |
| 67 | 71 |  | 
| 68 | 72 | unless options[:skip_agents] | 
| 69 | 73 | created_agents = agent_diffs.map do |agent_diff| | 
| @@ -32,7 +32,7 @@ | ||
| 32 | 32 |  | 
| 33 | 33 | <% agent.scenarios.each do |scenario| %> | 
| 34 | 34 | <li> | 
| 35 | -        <%= link_to "<span class='color-warning glyphicon glyphicon-remove-circle'></span> Remove from <span class='scenario label label-info'>#{h scenario.name}</span>".html_safe, leave_scenario_agent_path(agent, :scenario_id => scenario.to_param, :return => returnTo), method: :put, :tabindex => "-1" %> | |
| 35 | +        <%= link_to "<span class='color-warning glyphicon glyphicon-remove-circle'></span> Remove from #{scenario_label(scenario)}".html_safe, leave_scenario_agent_path(agent, :scenario_id => scenario.to_param, :return => returnTo), method: :put, :tabindex => "-1" %> | |
| 36 | 36 | </li> | 
| 37 | 37 | <% end %> | 
| 38 | 38 | <% end %> | 
| @@ -13,9 +13,8 @@ | ||
| 13 | 13 | <div class="alert alert-warning"> | 
| 14 | 14 | <span class='glyphicon glyphicon-warning-sign'></span> | 
| 15 | 15 | This Scenario already exists in your system. The import will update your existing | 
| 16 | - <span class='label label-info scenario'><%= @scenario_import.existing_scenario.name %></span> Scenario's title | |
| 17 | - and | |
| 18 | - description. Below you can customize how the individual agents get updated. | |
| 16 | + <%= scenario_label(@scenario_import.existing_scenario) %> Scenario's title, | |
| 17 | + description and tag colors. Below you can customize how the individual agents get updated. | |
| 19 | 18 | </div> | 
| 20 | 19 | <% end %> | 
| 21 | 20 |  | 
| @@ -15,6 +15,18 @@ | ||
| 15 | 15 | <%= f.text_field :name, :class => 'form-control', :placeholder => "Name your Scenario" %> | 
| 16 | 16 | </div> | 
| 17 | 17 | </div> | 
| 18 | + <div class="col-md-2"> | |
| 19 | + <div class="form-group"> | |
| 20 | + <%= f.label :tag_bg_color, "Tag Background Color" %> | |
| 21 | + <%= f.color_field :tag_bg_color, :class => 'form-control', :value => @scenario.tag_bg_color || default_scenario_bg_color %> | |
| 22 | + </div> | |
| 23 | + </div> | |
| 24 | + <div class="col-md-2"> | |
| 25 | + <div class="form-group"> | |
| 26 | + <%= f.label :tag_fg_color, "Tag Foreground Color" %> | |
| 27 | + <%= f.color_field :tag_fg_color, :class => 'form-control', :value => @scenario.tag_fg_color || default_scenario_fg_color %> | |
| 28 | + </div> | |
| 29 | + </div> | |
| 18 | 30 | </div> | 
| 19 | 31 |  | 
| 20 | 32 | <div class="row"> | 
| @@ -54,4 +66,4 @@ | ||
| 54 | 66 | </div> | 
| 55 | 67 | </div> | 
| 56 | 68 | </div> | 
| 57 | -<% end %> | |
| 69 | +<% end %> | 
| @@ -21,6 +21,7 @@ | ||
| 21 | 21 | <% @scenarios.each do |scenario| %> | 
| 22 | 22 | <tr> | 
| 23 | 23 | <td> | 
| 24 | + <%= scenario_label(scenario, content_tag(:i, '', class: 'glyphicon glyphicon-font')) %> | |
| 24 | 25 | <%= link_to(scenario.name, scenario) %> | 
| 25 | 26 | </td> | 
| 26 | 27 | <td><%= link_to pluralize(scenario.agents.count, "agent"), scenario %></td> | 
| @@ -47,4 +48,4 @@ | ||
| 47 | 48 | </div> | 
| 48 | 49 | </div> | 
| 49 | 50 | </div> | 
| 50 | -</div> | |
| 51 | +</div> | 
| @@ -2,7 +2,7 @@ | ||
| 2 | 2 | <div class='row'> | 
| 3 | 3 | <div class='col-md-12'> | 
| 4 | 4 | <div class="page-header"> | 
| 5 | - <h2>Share <span class='label label-info scenario'><%= @scenario.name %></span> with the world</h2> | |
| 5 | + <h2>Share <%= scenario_label(@scenario) %> with the world</h2> | |
| 6 | 6 | </div> | 
| 7 | 7 |  | 
| 8 | 8 | <p> | 
| @@ -30,4 +30,4 @@ | ||
| 30 | 30 | </div> | 
| 31 | 31 | </div> | 
| 32 | 32 | </div> | 
| 33 | -</div> | |
| 33 | +</div> | 
| @@ -2,7 +2,8 @@ | ||
| 2 | 2 | <div class='row'> | 
| 3 | 3 | <div class='col-md-12'> | 
| 4 | 4 | <div class="page-header"> | 
| 5 | - <h2><span class='label label-info scenario'><%= @scenario.name %></span> <%= "Public" if @scenario.public? %> Scenario</h2> | |
| 5 | + <h2><%= scenario_label(@scenario) %> <%= "Public" if @scenario.public? %> Scenario</h2> | |
| 6 | + | |
| 6 | 7 | </div> | 
| 7 | 8 |  | 
| 8 | 9 | <% if @scenario.description.present? %> | 
| @@ -5,14 +5,14 @@ | ||
| 5 | 5 | </head> | 
| 6 | 6 | <body> | 
| 7 | 7 | <% if @headline %> | 
| 8 | - <h1><%= @headline %></h1> | |
| 8 | + <h1><%= sanitize @headline %></h1> | |
| 9 | 9 | <% end %> | 
| 10 | 10 | <% @groups.each do |group| %> | 
| 11 | 11 | <div style='margin-bottom: 10px;'> | 
| 12 | - <div><%= group[:title] %></div> | |
| 12 | + <div><%= sanitize group[:title] %></div> | |
| 13 | 13 | <% group[:entries].each do |entry| %> | 
| 14 | 14 | <div style='margin-left: 10px;'> | 
| 15 | - <%= entry %> | |
| 15 | + <%= sanitize entry %> | |
| 16 | 16 | </div> | 
| 17 | 17 | <% end %> | 
| 18 | 18 | </div> | 
| @@ -0,0 +1,6 @@ | ||
| 1 | +class AddTagColorToScenarios < ActiveRecord::Migration | |
| 2 | + def change | |
| 3 | + add_column :scenarios, :tag_bg_color, :string | |
| 4 | + add_column :scenarios, :tag_fg_color, :string | |
| 5 | + end | |
| 6 | +end | 
| @@ -11,7 +11,7 @@ | ||
| 11 | 11 | # | 
| 12 | 12 | # It's strongly recommended that you check this file into your version control system. | 
| 13 | 13 |  | 
| 14 | -ActiveRecord::Schema.define(version: 20140811200922) do | |
| 14 | +ActiveRecord::Schema.define(version: 20140820003139) do | |
| 15 | 15 |  | 
| 16 | 16 | # These are extensions that must be enabled in order to support this database | 
| 17 | 17 | enable_extension "plpgsql" | 
| @@ -22,8 +22,8 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 22 | 22 | t.integer "level", default: 3, null: false | 
| 23 | 23 | t.integer "inbound_event_id" | 
| 24 | 24 | t.integer "outbound_event_id" | 
| 25 | - t.datetime "created_at", null: false | |
| 26 | - t.datetime "updated_at", null: false | |
| 25 | + t.datetime "created_at" | |
| 26 | + t.datetime "updated_at" | |
| 27 | 27 | end | 
| 28 | 28 |  | 
| 29 | 29 | create_table "agents", force: true do |t| | 
| @@ -36,8 +36,8 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 36 | 36 | t.datetime "last_check_at" | 
| 37 | 37 | t.datetime "last_receive_at" | 
| 38 | 38 | t.integer "last_checked_event_id" | 
| 39 | - t.datetime "created_at", null: false | |
| 40 | - t.datetime "updated_at", null: false | |
| 39 | + t.datetime "created_at" | |
| 40 | + t.datetime "updated_at" | |
| 41 | 41 | t.text "memory" | 
| 42 | 42 | t.datetime "last_web_request_at" | 
| 43 | 43 | t.integer "keep_events_for", default: 0, null: false | 
| @@ -45,8 +45,8 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 45 | 45 | t.datetime "last_error_log_at" | 
| 46 | 46 | t.boolean "propagate_immediately", default: false, null: false | 
| 47 | 47 | t.boolean "disabled", default: false, null: false | 
| 48 | - t.integer "service_id" | |
| 49 | 48 | t.string "guid", null: false | 
| 49 | + t.integer "service_id" | |
| 50 | 50 | end | 
| 51 | 51 |  | 
| 52 | 52 | add_index "agents", ["guid"], name: "index_agents_on_guid", using: :btree | 
| @@ -64,8 +64,8 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 64 | 64 | t.datetime "failed_at" | 
| 65 | 65 | t.string "locked_by" | 
| 66 | 66 | t.string "queue" | 
| 67 | - t.datetime "created_at", null: false | |
| 68 | - t.datetime "updated_at", null: false | |
| 67 | + t.datetime "created_at" | |
| 68 | + t.datetime "updated_at" | |
| 69 | 69 | end | 
| 70 | 70 |  | 
| 71 | 71 | add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree | 
| @@ -76,8 +76,8 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 76 | 76 | t.decimal "lat", precision: 15, scale: 10 | 
| 77 | 77 | t.decimal "lng", precision: 15, scale: 10 | 
| 78 | 78 | t.text "payload" | 
| 79 | - t.datetime "created_at", null: false | |
| 80 | - t.datetime "updated_at", null: false | |
| 79 | + t.datetime "created_at" | |
| 80 | + t.datetime "updated_at" | |
| 81 | 81 | t.datetime "expires_at" | 
| 82 | 82 | end | 
| 83 | 83 |  | 
| @@ -88,8 +88,8 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 88 | 88 | create_table "links", force: true do |t| | 
| 89 | 89 | t.integer "source_id" | 
| 90 | 90 | t.integer "receiver_id" | 
| 91 | - t.datetime "created_at", null: false | |
| 92 | - t.datetime "updated_at", null: false | |
| 91 | + t.datetime "created_at" | |
| 92 | + t.datetime "updated_at" | |
| 93 | 93 | t.integer "event_id_at_creation", default: 0, null: false | 
| 94 | 94 | end | 
| 95 | 95 |  | 
| @@ -107,14 +107,16 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 107 | 107 | add_index "scenario_memberships", ["scenario_id"], name: "index_scenario_memberships_on_scenario_id", using: :btree | 
| 108 | 108 |  | 
| 109 | 109 | create_table "scenarios", force: true do |t| | 
| 110 | - t.string "name", null: false | |
| 111 | - t.integer "user_id", null: false | |
| 110 | + t.string "name", null: false | |
| 111 | + t.integer "user_id", null: false | |
| 112 | 112 | t.datetime "created_at" | 
| 113 | 113 | t.datetime "updated_at" | 
| 114 | 114 | t.text "description" | 
| 115 | - t.boolean "public", default: false, null: false | |
| 116 | - t.string "guid", null: false | |
| 115 | + t.boolean "public", default: false, null: false | |
| 116 | + t.string "guid", null: false | |
| 117 | 117 | t.string "source_url" | 
| 118 | + t.string "tag_bg_color" | |
| 119 | + t.string "tag_fg_color" | |
| 118 | 120 | end | 
| 119 | 121 |  | 
| 120 | 122 | add_index "scenarios", ["user_id", "guid"], name: "index_scenarios_on_user_id_and_guid", unique: true, using: :btree | 
| @@ -136,14 +138,14 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 136 | 138 |  | 
| 137 | 139 | add_index "services", ["provider"], name: "index_services_on_provider", using: :btree | 
| 138 | 140 | add_index "services", ["uid"], name: "index_services_on_uid", using: :btree | 
| 139 | - add_index "services", ["user_id", "global"], name: "index_accounts_on_user_id_and_global", using: :btree | |
| 141 | + add_index "services", ["user_id", "global"], name: "index_services_on_user_id_and_global", using: :btree | |
| 140 | 142 |  | 
| 141 | 143 | create_table "user_credentials", force: true do |t| | 
| 142 | 144 | t.integer "user_id", null: false | 
| 143 | 145 | t.string "credential_name", null: false | 
| 144 | 146 | t.text "credential_value", null: false | 
| 145 | - t.datetime "created_at", null: false | |
| 146 | - t.datetime "updated_at", null: false | |
| 147 | + t.datetime "created_at" | |
| 148 | + t.datetime "updated_at" | |
| 147 | 149 | t.string "mode", default: "text", null: false | 
| 148 | 150 | end | 
| 149 | 151 |  | 
| @@ -160,8 +162,8 @@ ActiveRecord::Schema.define(version: 20140811200922) do | ||
| 160 | 162 | t.datetime "last_sign_in_at" | 
| 161 | 163 | t.string "current_sign_in_ip" | 
| 162 | 164 | t.string "last_sign_in_ip" | 
| 163 | - t.datetime "created_at", null: false | |
| 164 | - t.datetime "updated_at", null: false | |
| 165 | + t.datetime "created_at" | |
| 166 | + t.datetime "updated_at" | |
| 165 | 167 | t.boolean "admin", default: false, null: false | 
| 166 | 168 | t.integer "failed_attempts", default: 0 | 
| 167 | 169 | t.string "unlock_token" | 
| @@ -16,6 +16,8 @@ class AgentsExporter | ||
| 16 | 16 | :description => options[:description].presence || 'No description provided', | 
| 17 | 17 | :source_url => options[:source_url], | 
| 18 | 18 | :guid => options[:guid], | 
| 19 | + :tag_fg_color => options[:tag_fg_color], | |
| 20 | + :tag_bg_color => options[:tag_bg_color], | |
| 19 | 21 | :exported_at => Time.now.utc.iso8601, | 
| 20 | 22 |        :agents => agents.map { |agent| agent_as_json(agent) }, | 
| 21 | 23 | :links => links | 
| @@ -51,4 +53,4 @@ class AgentsExporter | ||
| 51 | 53 | options[:propagate_immediately] = agent.propagate_immediately if agent.can_receive_events? | 
| 52 | 54 | end | 
| 53 | 55 | end | 
| 54 | -end | |
| 56 | +end | 
| @@ -50,6 +50,8 @@ describe ScenariosController do | ||
| 50 | 50 | assigns(:exporter).options[:description].should == scenarios(:bob_weather).description | 
| 51 | 51 | assigns(:exporter).options[:agents].should == scenarios(:bob_weather).agents | 
| 52 | 52 | assigns(:exporter).options[:guid].should == scenarios(:bob_weather).guid | 
| 53 | + assigns(:exporter).options[:tag_fg_color].should == scenarios(:bob_weather).tag_fg_color | |
| 54 | + assigns(:exporter).options[:tag_bg_color].should == scenarios(:bob_weather).tag_bg_color | |
| 53 | 55 | assigns(:exporter).options[:source_url].should be_falsey | 
| 54 | 56 | response.headers['Content-Disposition'].should == 'attachment; filename="bob-s-weather-alert-scenario.json"' | 
| 55 | 57 | response.headers['Content-Type'].should == 'application/json; charset=utf-8' | 
| @@ -0,0 +1,30 @@ | ||
| 1 | +require 'spec_helper' | |
| 2 | + | |
| 3 | +describe ScenarioHelper do | |
| 4 | +  let(:scenario) { users(:bob).scenarios.build(name: 'Scene', tag_fg_color: '#AAAAAA', tag_bg_color: '#000000') } | |
| 5 | + | |
| 6 | + describe '#style_colors' do | |
| 7 | + it 'returns a css style-formated version of the scenario foreground and background colors' do | |
| 8 | + style_colors(scenario).should == "color:#AAAAAA;background-color:#000000" | |
| 9 | + end | |
| 10 | + | |
| 11 | + it 'defauls foreground and background colors' do | |
| 12 | + scenario.tag_fg_color = nil | |
| 13 | + scenario.tag_bg_color = nil | |
| 14 | + style_colors(scenario).should == "color:#FFFFFF;background-color:#5BC0DE" | |
| 15 | + end | |
| 16 | + end | |
| 17 | + | |
| 18 | + describe '#scenario_label' do | |
| 19 | + it 'creates a scenario label with the scenario name' do | |
| 20 | + scenario_label(scenario).should == | |
| 21 | + '<span class="label scenario" style="color:#AAAAAA;background-color:#000000">Scene</span>' | |
| 22 | + end | |
| 23 | + | |
| 24 | + it 'creates a scenario label with the given text' do | |
| 25 | + scenario_label(scenario, 'Other').should == | |
| 26 | + '<span class="label scenario" style="color:#AAAAAA;background-color:#000000">Other</span>' | |
| 27 | + end | |
| 28 | + end | |
| 29 | + | |
| 30 | +end | 
| @@ -7,9 +7,13 @@ describe AgentsExporter do | ||
| 7 | 7 |      let(:name) { "My set of Agents" } | 
| 8 | 8 |      let(:description) { "These Agents work together nicely!" } | 
| 9 | 9 |      let(:guid) { "some-guid" } | 
| 10 | +    let(:tag_fg_color) { "#ffffff" } | |
| 11 | +    let(:tag_bg_color) { "#000000" } | |
| 10 | 12 |      let(:source_url) { "http://yourhuginn.com/scenarios/2/export.json" } | 
| 11 | 13 |      let(:agent_list) { [agents(:jane_weather_agent), agents(:jane_rain_notifier_agent)] } | 
| 12 | -    let(:exporter) { AgentsExporter.new(:agents => agent_list, :name => name, :description => description, :source_url => source_url, :guid => guid) } | |
| 14 | +    let(:exporter) { AgentsExporter.new( | |
| 15 | + :agents => agent_list, :name => name, :description => description, :source_url => source_url, | |
| 16 | + :guid => guid, :tag_fg_color => tag_fg_color, :tag_bg_color => tag_bg_color) } | |
| 13 | 17 |  | 
| 14 | 18 | it "outputs a structure containing name, description, the date, all agents & their links" do | 
| 15 | 19 | data = exporter.as_json | 
| @@ -17,6 +21,8 @@ describe AgentsExporter do | ||
| 17 | 21 | data[:description].should == description | 
| 18 | 22 | data[:source_url].should == source_url | 
| 19 | 23 | data[:guid].should == guid | 
| 24 | + data[:tag_fg_color].should == tag_fg_color | |
| 25 | + data[:tag_bg_color].should == tag_bg_color | |
| 20 | 26 | Time.parse(data[:exported_at]).should be_within(2).of(Time.now.utc) | 
| 21 | 27 |        data[:links].should == [{ :source => 0, :receiver => 1 }] | 
| 22 | 28 |        data[:agents].should == agent_list.map { |agent| exporter.agent_as_json(agent) } | 
| @@ -58,4 +64,4 @@ describe AgentsExporter do | ||
| 58 | 64 | AgentsExporter.new(:name => ",,").filename.should == "exported-agents.json" | 
| 59 | 65 | end | 
| 60 | 66 | end | 
| 61 | -end | |
| 67 | +end | 
| @@ -3,6 +3,8 @@ require 'spec_helper' | ||
| 3 | 3 | describe ScenarioImport do | 
| 4 | 4 |    let(:user) { users(:bob) } | 
| 5 | 5 |    let(:guid) { "somescenarioguid" } | 
| 6 | +  let(:tag_fg_color) { "#ffffff" } | |
| 7 | +  let(:tag_bg_color) { "#000000" } | |
| 6 | 8 |    let(:description) { "This is a cool Huginn Scenario that does something useful!" } | 
| 7 | 9 |    let(:name) { "A useful Scenario" } | 
| 8 | 10 |    let(:source_url) { "http://example.com/scenarios/2/export.json" } | 
| @@ -58,10 +60,12 @@ describe ScenarioImport do | ||
| 58 | 60 | } | 
| 59 | 61 | end | 
| 60 | 62 | let(:valid_parsed_data) do | 
| 61 | -    {  | |
| 63 | +    { | |
| 62 | 64 | :name => name, | 
| 63 | 65 | :description => description, | 
| 64 | 66 | :guid => guid, | 
| 67 | + :tag_fg_color => tag_fg_color, | |
| 68 | + :tag_bg_color => tag_bg_color, | |
| 65 | 69 | :source_url => source_url, | 
| 66 | 70 | :exported_at => 2.days.ago.utc.iso8601, | 
| 67 | 71 | :agents => [ | 
| @@ -154,7 +158,7 @@ describe ScenarioImport do | ||
| 154 | 158 | end | 
| 155 | 159 | end | 
| 156 | 160 | end | 
| 157 | - | |
| 161 | + | |
| 158 | 162 | describe "#dangerous?" do | 
| 159 | 163 | it "returns false on most Agents" do | 
| 160 | 164 | ScenarioImport.new(:data => valid_data).should_not be_dangerous | 
| @@ -183,6 +187,8 @@ describe ScenarioImport do | ||
| 183 | 187 | scenario_import.scenario.name.should == name | 
| 184 | 188 | scenario_import.scenario.description.should == description | 
| 185 | 189 | scenario_import.scenario.guid.should == guid | 
| 190 | + scenario_import.scenario.tag_fg_color.should == tag_fg_color | |
| 191 | + scenario_import.scenario.tag_bg_color.should == tag_bg_color | |
| 186 | 192 | scenario_import.scenario.source_url.should == source_url | 
| 187 | 193 | scenario_import.scenario.public.should be_falsey | 
| 188 | 194 | end | 
| @@ -281,6 +287,8 @@ describe ScenarioImport do | ||
| 281 | 287 |  | 
| 282 | 288 | existing_scenario.reload | 
| 283 | 289 | existing_scenario.guid.should == guid | 
| 290 | + existing_scenario.tag_fg_color.should == tag_fg_color | |
| 291 | + existing_scenario.tag_bg_color.should == tag_bg_color | |
| 284 | 292 | existing_scenario.description.should == description | 
| 285 | 293 | existing_scenario.name.should == name | 
| 286 | 294 | existing_scenario.source_url.should == source_url | 
| @@ -463,4 +471,4 @@ describe ScenarioImport do | ||
| 463 | 471 | end | 
| 464 | 472 | end | 
| 465 | 473 | end | 
| 466 | -end | |
| 474 | +end | 
| @@ -20,6 +20,30 @@ describe Scenario do | ||
| 20 | 20 | new_instance.should_not be_valid | 
| 21 | 21 | end | 
| 22 | 22 |  | 
| 23 | + it "validates tag_fg_color is hex color" do | |
| 24 | + new_instance.tag_fg_color = '#N07H3X' | |
| 25 | + new_instance.should_not be_valid | |
| 26 | + new_instance.tag_fg_color = '#BADA55' | |
| 27 | + new_instance.should be_valid | |
| 28 | + end | |
| 29 | + | |
| 30 | + it "allows nil tag_fg_color" do | |
| 31 | + new_instance.tag_fg_color = nil | |
| 32 | + new_instance.should be_valid | |
| 33 | + end | |
| 34 | + | |
| 35 | + it "validates tag_bg_color is hex color" do | |
| 36 | + new_instance.tag_bg_color = '#N07H3X' | |
| 37 | + new_instance.should_not be_valid | |
| 38 | + new_instance.tag_bg_color = '#BADA55' | |
| 39 | + new_instance.should be_valid | |
| 40 | + end | |
| 41 | + | |
| 42 | + it "allows nil tag_bg_color" do | |
| 43 | + new_instance.tag_bg_color = nil | |
| 44 | + new_instance.should be_valid | |
| 45 | + end | |
| 46 | + | |
| 23 | 47 | it "only allows Agents owned by user" do | 
| 24 | 48 | new_instance.agent_ids = [agents(:bob_website_agent).id] | 
| 25 | 49 | new_instance.should be_valid |